package prender;

import org.apache.log4j.Logger;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

/**
 * Initialization & cleanup at Web Application level for prender.
 * @author Stone Zhong
 *
 */
public class ApplicationListener implements ServletContextListener {
	private static final Logger logger = Logger.getLogger("ApplicationListener");
	
	/**
	 * This name need to be unique and not conflict against other names.
	 */
	static final String THREAD_POOL_KEY = "prender.ApplicationListener:threadPool";
	static final String THREAD_POOL_THREAD_COUNT = "prender.threadPoolCount";
	
	private ExecutorService threadPool = null;

	/**
	 * prender cleanup for Web Application.
	 * 
	 */
	@Override
	public void contextDestroyed(ServletContextEvent event) {
		if (logger.isDebugEnabled()) {
			logger.debug("contextDestroyed: Enter");
		}
		threadPool.shutdown();
		for (;;) { 
			try {
				threadPool.awaitTermination(10, TimeUnit.SECONDS);
				break;
			} catch (InterruptedException e) {
			}
		}
		if (logger.isDebugEnabled()) {
			logger.debug("contextDestroyed: Leave");
		}
	}

	// the number should be between 4 and 200
	private int getThreadCount(ServletContext context) {
		int threadCount = 0;
		try {
			String sThreadCount = context.getInitParameter(THREAD_POOL_THREAD_COUNT);
			threadCount = Integer.valueOf(sThreadCount);
		} catch (NumberFormatException e) {
		}
		if (threadCount < 4) {
			return 4;
		}
		if (threadCount > 200) {
			return 200;
		}
		return threadCount;
	}
	
	/**
	 * prender initialization for Web Application.
	 *  
	 */
	@Override
	public void contextInitialized(ServletContextEvent event) {
		if (logger.isDebugEnabled()) {
			logger.debug("contextInitialized: Enter");
		}
		
		int threadCount = getThreadCount(event.getServletContext());
		logger.debug(String.format("contextInitialized: threadCount = [%d]\n", threadCount));  
		
		threadPool = Executors.newFixedThreadPool(threadCount);
		event.getServletContext().setAttribute(THREAD_POOL_KEY, threadPool);
		
		if (logger.isDebugEnabled()) {
			logger.debug("contextInitialized: Leave");
		}
	}
}
